package com.exercise.ThreadCommunication;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProducerConsumerExampleCondition {
    public static void main(String[] args) {
        Buffer2 buffer2 = new Buffer2(2);

        Thread producer = new Thread(() -> {
            int i = 0;
            try {
                while (true) {
                    buffer2.produce(i++); // 生产一个数据项 / Produce an item
                    Thread.sleep(100); // 模拟生产耗时 / Simulate production delay
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // 恢复中断状态 / Restore interrupt status
            }
        }, "producer");

        Thread consumer = new Thread(() -> {
            try {
                while (true) {
                    buffer2.consume(); // 消费一个数据项 / Consume an item
                    Thread.sleep(200); // 模拟消费耗时 / Simulate consumption delay
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // 恢复中断状态 / Restore interrupt status
            }
        }, "consumer");

        producer.start();
        consumer.start();

    }

}

class Buffer2{
    private final Queue<Integer> queue = new LinkedList<>(); // 存储数据项的队列 / Shared queue (buffer)
    private final int capacity;         // 缓冲区最大容量 / Maximum capacity of the buffer

    private final Lock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();

    public Buffer2(int capacity) {
        this.capacity = capacity;
    }

    public void produce(int item) throws InterruptedException {
        lock.lock();
        try{
            while(queue.size() == capacity){
                System.out.println(Thread.currentThread().getName() + "waiting, buffer is full");
                // 如果缓冲区满了，进入等待 / Wait if the buffer is full
                // 等待为非满
                notFull.await();
            }

            queue.offer(item); // 添加数据到缓冲区 / Add item to buffer
            System.out.println(Thread.currentThread().getName() + " produced: " + item);
            // 通知等待的消费者线程 / Notify waiting consumers
            notEmpty.signalAll();
        }finally {
            lock.unlock();
        }
    }

    public void consume(){
        lock.lock();
        try{
            while (queue.isEmpty()) {
                System.out.println(Thread.currentThread().getName() + " waiting, buffer is empty");
                // 如果缓冲区为空，进入等待 / Wait if buffer is empty
                // 等待为非空
                notEmpty.await();
            }
            int item = queue.poll(); // 从队列头部取出数据 / Remove item from buffer
            System.out.println(Thread.currentThread().getName() + " consumed: " + item);
            // 通知等待的生产者线程 / Notify waiting producers
            notFull.signalAll();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }

}
